# 导入socket库:
import socket,threading,time 
import hmac
import  hashlib
import ast
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT


prime = 148300296503541537023967543385571281566188269121696986355794642903163978311488366178620508621203382790644644256351530344017086776119734526929467544594283880389370982620148075975876610977802799762624795305966277480303398775064011730140292446255046328316204433780624821532022148316432675132662755400581378870583
key_s = b'\x1a\xde\x9b\xda\xadNq\xf4\xa5\x04g\x02\x99E\x8d\xcf[\x0f\xa6Dx\xe7\t\xbb\x1e\xb2n\xbd|h\xcf\x16'
iv = 'gvmr10z4pc6xqn3l'
iv_bytes = bytes(iv,encoding='utf8')

def sm4_cbc_dec(ciphertext, iv, key):
    crypt_sm4 = CryptSM4()
    crypt_sm4.set_key(key, SM4_DECRYPT)
    plaintext_bytes = crypt_sm4.crypt_cbc(iv, ciphertext)

    return plaintext_bytes

def exgcd(a, b):
    if b == 0:
        return 1, 0, a
    else:
        x, y, q = exgcd(b, a % b)
        x, y = y, (x - (a // b) * y)
        return x, y, q

# 扩展欧几里得求逆元
def ModReverse(a,p):
    x, y, q = exgcd(a,p)
    if q != 1:
        raise Exception("No solution.")
    else:
        return (x + p) % p #防止负数

#获取column，column_msk
def get_column(prime,T):
    column_msk = []
    column = []
    for i in range(0,len(T)):
        for j in range(1,len(Ir)):
            e = (T[i][1] * Ir[j]) % prime

            m = (T[i][2] * ModReverse(e,prime)) % prime
            mac =hmac.new(key_s,bytes(str(e^m^ModReverse(Ir[j],prime)),encoding='utf-8'),digestmod=hashlib.sha256).hexdigest()
            mac = int(mac.upper(),16)
            # print(mac)
            if mac ==T[i][0]:
                column.append(j)
                column_msk.append(m)

    return column,column_msk

# 获取encrypted_file文件指针，key_s为哈希链的密钥
def get_encryptedfile(column,key_s,column_msk,T,I,Ic,s1):
    encrypted_file = []
    if len(T)!= len(column):
        print('no result')
    else:
        for i in range(1,len(Ic)):
            if len(column) == 0:
                print('no result')
                break
            else:
                tag_1 = [1] * s1
                tag_2 = [0] * s1
                for j in range(0,len(column)-1):
                    for m in range(0,s1):
                        if tag_1[m] == 1:
                            for n in range(0,s1):
                                front = I[i][column[j]][m]-column_msk[j]
                                mac_front = I[i][column[j + 1]][n] - column_msk[j + 1]
                                value = hmac.new(key_s,str(front).encode('utf-8'),digestmod=hashlib.sha256).hexdigest()
                                if int(value.upper(),16) == mac_front:
                                    tag_2[n] = 1
                                    break
                                else:
                                    continue

                        else:
                            continue
                    tag_1 = tag_2.copy()
                    tag_2 = [0] * s1

                mark = 0
                for tag in tag_1:
                    if tag == 1:
                        mark = 1
                        break
                    else:
                        continue

                if mark == 1:
                    encrypted_file.append([Ic[i]])
    return encrypted_file


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口:
s.bind(('0.0.0.0', 2000))
s.listen(5)
sk=socket.socket()
sk.bind(('0.0.0.0',5000)) #申请操作系统资源
sk.listen(5)
print('Waiting for connection...')
def tcplink(sock, addr):
    all=''
    Ica=''
    columna=''
    column_mska=''
    Ta=''
    Ira=''
    s1a=''   #int 型
    Ia=''

    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')

    while True: 
        data = sock.recv(1024)
        all=all+data.decode('utf-8')
        if not data or data.decode('utf-8') == '**':
            break
    sock.send(b'Welcome!')
    all=all.split("**")
    columna=all[0]
    column_mska=all[1]
    Ta=all[2]
    Ira=all[3]
    Ica=all[4]
    Ia=all[5]
    s1a=all[6]

    column=[]
    column_msk=[]
    Ir=[]
    Ic=[]
    I=[]
    T=[]
    s1=0

    column= ast.literal_eval(columna)
    column_msk= ast.literal_eval(column_mska)
    T=ast.literal_eval(Ta)
    Ir= ast.literal_eval(Ira)
    Ic= ast.literal_eval(Ica)
    I= ast.literal_eval(Ia)
    s1=int(s1a)
 
    encrypted_file = []
    encrypted_file = get_encryptedfile(column,key_s,column_msk,T,I,Ic,s1)
    print(encrypted_file)
    sock.close()

    encrypted_filestr=str(encrypted_file)
    encrypted_filestr=encrypted_filestr+"*"
    #sock.send(encrypted_file.encode('utf-8'))
    conn, addr = sk.accept() #conn里存储的是一个客户端和server端连接信息
    conn.send(encrypted_filestr.encode('utf-8'))
    conn.close() #挥手断开连接
    #sk.close()
# 根据文件索引打印搜索的内容所在的句子(客户端



while True:
    # 接受一个新连接:
    sock, addr = s.accept()
    # 创建新线程来处理TCP连接:
    t = threading.Thread(target=tcplink, args=(sock, addr))
    t.start()







